Skip to content

doc: add explanation for multiple Transfer-Encoding values #39496

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: main
Choose a base branch
from

Conversation

samuel871211
Copy link
Contributor

Description

Motivation

Currently, the MDN document doesn't explain the meaning of multiple values of Transfer-Encoding.

Additional details

https://datatracker.ietf.org/doc/html/rfc9112#section-6.1-6

For example,

Transfer-Encoding: gzip, chunked

indicates that the content has been compressed using the gzip coding and then chunked using the chunked coding while forming the message body.

Related issues and pull requests

@samuel871211 samuel871211 requested a review from a team as a code owner May 13, 2025 07:43
@samuel871211 samuel871211 requested review from hamishwillee and removed request for a team May 13, 2025 07:43
@github-actions github-actions bot added Content:HTTP HTTP docs size/xs [PR only] 0-5 LoC changed labels May 13, 2025
Copy link
Contributor

github-actions bot commented May 13, 2025

Preview URLs

Flaws (3)

URL: /en-US/docs/Web/HTTP/Reference/Headers/Transfer-Encoding
Title: Transfer-Encoding header
Flaw count: 3

  • unknown:
    • No generic content config found
    • no blog root
    • no blog root

(comment last updated: 2025-05-30 01:39:53)

@github-actions github-actions bot added size/s [PR only] 6-50 LoC changed and removed size/xs [PR only] 0-5 LoC changed labels May 16, 2025
Copy link
Collaborator

@hamishwillee hamishwillee left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for this @samuel871211

I have modified it because the document had bigger problems based on my reading of the spec. In particular, the meaning of the encoding differs depending on whether it is a request or a response.

My read of the spec is that:

  • In a request the values indicate the supported encodings that the server is expected to choose from. Essentially the client is saying if it gets a message with these encodings it can decode them. You can specify multiple directives, comma separated. I assume that they are ordered by preference, but I don't see that stated.
  • In a response directives indicate the encoding used for a particular message.
    • You could use multiple compression directives, but you never would - as it makes no sense.
    • However you can use any compression with chunked. The spec says that you can only chunk once and at the end. So a response with compression and chunking will always look like gzip, chunked. It can't look like chunked, gzip,.

@bsmth Can you take over review, as I am no longer objective?
I am fairly sure of this from the spec and "similar headers", but not certain.

@hamishwillee hamishwillee requested a review from bsmth May 16, 2025 01:57
Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
@samuel871211
Copy link
Contributor Author

  • In a request the values indicate the supported encodings that the server is expected to choose from. Essentially the client is saying if it gets a message with these encodings it can decode them. You can specify multiple directives, comma separated. I assume that they are ordered by preference, but I don't see that stated.

@hamishwillee Thanks for the review. This sounds like the definition of Accept-Encoding. Would it be possible to share the documents you read?

@hamishwillee
Copy link
Collaborator

@samuel871211 Yes, I am very much basing this on Accept-Encoding and Content-Encoding. I believe this does the same kind of thing, but using the same header for both the request and response.
So in the request we're using Transfer-Encoding header to indicate the supported encodings of the client, and in the response we're using it to indicate the actual values.

The spec really doesn't say much about its use in the request other than it can be present in HTTP1/1, so I'm really just inferring what it is for. BUT, we do know that this information is missing so we need to say something.

I'm also not 100% sure this bit is correct:L

Transfer-Encoding is a hop-by-hop header, that is applied to a message between two nodes, not to a resource itself. Each segment of a multi-node connection can use different Transfer-Encoding values.

I mean I think it is true, but perhaps incomplete. The spec seems to indicate that a hop could also apply additional encoding. The reason I did not try and capture this is that I can't see where you would do this. I.e. if you're already gzip you won't compress. Perhaps you would add chunked though?

Upshot, deferring to @bsmth because he has worked on this recently.

@@ -13,7 +13,16 @@ The HTTP **`Transfer-Encoding`** {{glossary("request header", "request")}} and {
Each segment of a multi-node connection can use different `Transfer-Encoding` values.
If you want to compress data over the whole connection, use the end-to-end {{HTTPHeader("Content-Encoding")}} header instead.

When present on a response to a {{HTTPMethod("HEAD")}} request that has no body, it indicates the value that would have applied to the corresponding {{HTTPMethod("GET")}} message.
When present in a request it indicates the encodings supported by the client.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Not quite, the TE header is supposed to be used for this, see https://datatracker.ietf.org/doc/html/rfc9112#section-7.4

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So my understanding is that Transfer-Encoding on a request indicates what encodings were used on that request - practically speaking this is probably only going to be chunked and even at that, I think it's rare.

Transfer-Encoding:

is primarily intended to accurately delimit dynamically generated content. It also serves to distinguish encodings that are only applied in transit from the encodings that are a characteristic of the selected representation.

See https://httpwg.org/specs/rfc9112.html#field.transfer-encoding

Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Thanks for finding that! I have tried to update this bit in https://github.com/mdn/content/pull/39496/files#r2114994600

@bsmth
Copy link
Member

bsmth commented May 27, 2025

I mean I think it is true, but perhaps incomplete. The spec seems to indicate that a hop could also apply additional encoding. The reason I did not try and capture this is that I can't see where you would do this. I.e. if you're already gzip you won't compress. Perhaps you would add chunked though?

Upshot, deferring to @bsmth because he has worked on this recently.

Thanks, Hamish. Looks like there's been lots of confusion about Transfer-Encoding (TE) v Content-Encoding (CE) over the years, and:

The web has definitely centered around content-encoding rather than t-e,

Stdlibs like in Go basically use CE for compression (end-to-end) and TE to indicate message chunking.

For those reasons, we should make that a bit clear about what's permitted in the spec, and what happens in the real world - and this hop-by-hop note is good, and to point to Content-Encoding and Accept-Encoding for requesting & sending compressed resources.

@hamishwillee hamishwillee requested a review from bsmth May 30, 2025 01:39
@hamishwillee
Copy link
Collaborator

@bsmth I've included your comment pretty much verbatim. Sufficient?

Comment on lines +16 to +25
When present in a request it indicates the encodings applied to the request body.
While multiple encodings may be specified, and the client must support the `chunked` directive, in practice this header is rarely used in requests (and if used, only with `chunked`).

When present on a response it indicates the compression used on the message, and/or whether the message has been chunked.
Note that if the message is chunked, this must be applied last, after any other compression.
For example, `Transfer-Encoding: gzip, chunked` indicates that the content has been compressed using the gzip coding and then chunked using the chunked coding while forming the message body.
While multiple compression options may be specified in theory, there is no practical value in applying more than one compression.

The response to a {{HTTPMethod("HEAD")}} request has no body and no transfer encoding, so the header is optional.
When present it indicates the value that would have applied to the corresponding response to a {{HTTPMethod("GET")}} message, if that `GET` request did not include a preferred `Transfer-Encoding`.
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think this covers it mostly, I don't think it's necessary to talk about requests and responses separately as the same applies:

Suggested change
When present in a request it indicates the encodings applied to the request body.
While multiple encodings may be specified, and the client must support the `chunked` directive, in practice this header is rarely used in requests (and if used, only with `chunked`).
When present on a response it indicates the compression used on the message, and/or whether the message has been chunked.
Note that if the message is chunked, this must be applied last, after any other compression.
For example, `Transfer-Encoding: gzip, chunked` indicates that the content has been compressed using the gzip coding and then chunked using the chunked coding while forming the message body.
While multiple compression options may be specified in theory, there is no practical value in applying more than one compression.
The response to a {{HTTPMethod("HEAD")}} request has no body and no transfer encoding, so the header is optional.
When present it indicates the value that would have applied to the corresponding response to a {{HTTPMethod("GET")}} message, if that `GET` request did not include a preferred `Transfer-Encoding`.
If multiple encodings are specified, for example, `Transfer-Encoding: gzip, chunked`, this indicates that message content has first been compressed using gzip, and then chunked for transit.
There is no value in applying more than one compression method, as this may actually increase the message size.
In practice, this header rarely contains a value other than `chunked` to accurately delimit dynamically-generated content.
The header is optional in responses to a {{HTTPMethod("HEAD")}} request as these messages have no body and, therefore, no transfer encoding.
When present, it indicates the value that would have applied to the corresponding response to a {{HTTPMethod("GET")}} message, if that `GET` request did not include a preferred `Transfer-Encoding`.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@hamishwillee does this make sense?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Content:HTTP HTTP docs size/s [PR only] 6-50 LoC changed
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants